package com.mybatis.template;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ZipUtil;
import com.mybatis.constant.Constants;
import com.mybatis.dto.request.CodeGenerationParam;
import com.mybatis.handler.AsyncGenerator;
import com.mybatis.message.Result;
import com.mybatis.message.ReturnResult;
import com.mybatis.strategy.DatabaseStrategy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Map;

/**
 * @desc: 抽象生成代码模板
 * @projectName: mybatis-generator-parent
 * @author: xhs
 * @date: 2023-7-22 022 17:32
 * @version: JDK 1.8
 */
@Slf4j
@Component
public abstract class AbstractGeneratorTemplate {

    @Resource
    private Map<String, DatabaseStrategy> databaseStrategyMap;
    @Resource
    private AsyncGenerator asyncGenerator;


    /**
     * 生成代码
     *
     * @param codeGenerationParam 生成代码入参
     * @return ReturnResult
     */
    public ReturnResult<Object> generatorCode(CodeGenerationParam codeGenerationParam) {
        log.info("{}使用{}生成代码 start{}", Constants.START, codeGenerationParam.getOrmType(), Constants.END);
        // 1.生成代码
        DatabaseStrategy databaseStrategy = databaseStrategyMap.get(codeGenerationParam.getDataBaseType());
        boolean generator = getGenerator(codeGenerationParam, databaseStrategy);
        log.info("{}使用{}生成代码 end {} {}", Constants.START, codeGenerationParam.getOrmType(), generator, Constants.END);
        if (!generator) {
            return ReturnResult.build(Result.GENERATOR_CODE_ERROR);
        }
        log.info("{}生成压缩包 start{}", Constants.START, Constants.END);
        // 2.打包生成的代码
        String fileUrl = packGeneratorCode(codeGenerationParam.getBasePackage());
        log.info("{}生成压缩包 end{}", Constants.START, Constants.END);
        // 3.异步记录日志
        asyncGenerator.generatorCodeLog(codeGenerationParam);
        return ReturnResult.build(Result.GENERATOR_CODE_SUCCESS).setData(fileUrl);
    }

    /**
     * 生成代码
     *
     * @param codeGenerationParam 生成代码入参
     * @param databaseStrategy    数据库策略类
     * @return boolean
     */
    protected abstract boolean getGenerator(CodeGenerationParam codeGenerationParam, DatabaseStrategy databaseStrategy);

    /**
     * 打包生成的代码
     */
    protected String packGeneratorCode(String packageName) {
        // 项目根目录
        String projectPath = System.getProperty(Constants.USER_DIR);
        // 已经生成的代码路径
        String outFilePath = projectPath + Constants.FILE_OUTPUT_DIR;
        // 根包名
        String replace = packageName.replace(".", "/");
        // 生成的代码目录不包括根包(如：com.baidu)
        String filePath = outFilePath + "/" + replace;
        // 打包后的路径
        String fileUrl = projectPath + "/" + packageName + Constants.ZIP_NAME;
        // 打包
        ZipUtil.zip(filePath, fileUrl);
        // 打包完成后删除生成代码的目录
        FileUtil.del(filePath);
        // 路径中的 "\\" 转为 "/"
        return fileUrl.replace("\\", "/");
    }

}
